'''
Created on 31.7.2011

@author: gilead
'''

from math import cos, sin, radians

from direct.task import Task
from panda3d.core import Vec4 #@UnresolvedImport
from panda3d.core import MeshDrawer,Vec3,VBase4 #@UnresolvedImport
from panda3d.core import ColorWriteAttrib #@UnresolvedImport
from panda3d.core import PointLight, Point3 #@UnresolvedImport
from time import time

class Laser(object):
    class Beam(object):
        def __init__(self, duration, maxwidth, turret, tgtNodePath, tgtOffset, color):
            self.duration = duration
            self.maxwidth = maxwidth
            # TODO: use turrets and nodepaths instead of fixed locations
            self.turret = turret
            self.tgtNodePath = tgtNodePath
            self.tgtOffset = tgtOffset
            self.color = color
            self.starttime = time()
            
            self.createLight()
            
        def createLight(self):
            self.attackingShip = self.turret.getShip()
            self.plight = PointLight('turret light')
            self.plight.setColor(self.color)
            self.plightNP = self.turret.attachNewNode(self.plight)
            self.plight.setAttenuation(Point3(0, 0, 0.5))
            self.attackingShip.setLight(self.plightNP)
            
        def removeLight(self):
            self.attackingShip.clearLight(self.plightNP)
            self.plight = None
            self.plightNP.removeNode() # detaches from parent and deletes the node
    
    def __init__(self, world):
        '''
        Constructor
        '''
        self.world = world # kaytetaan turrettien ja nodepathien sijaintien selvittamiseen
        self.generator = MeshDrawer()
        self.generator.setBudget(1000)
        generatorNode = self.generator.getRoot()
        generatorNode.reparentTo(render)
        generatorNode.setAttrib(ColorWriteAttrib.make(ColorWriteAttrib.CAll))
        
        generatorNode.setDepthWrite(False)
        generatorNode.setTransparency(True)
        generatorNode.setTwoSided(True)
        generatorNode.setBin("fixed",0)
        generatorNode.setLightOff(True)
        
        taskMgr.add(self.laserUpdateTask, "laserUpdateTask")
        self.beams = []
        
    def add(self, duration, maxwidth, originTurret, tgtNodePath, tgtOffset, color):
        beam = Laser.Beam(duration, maxwidth, originTurret, tgtNodePath, tgtOffset, color)
        self.beams.append(beam)
    
    def getOffSet(self, beam):
        heading = radians(beam.tgtNodePath.getH())
        # TODO: toimii pituussuunnan kanssa. leveys pitaisi ottaa jotenkin myos huomioon
        return Vec3(beam.tgtOffset.getX() * cos(heading), 
                    beam.tgtOffset.getX() * sin(heading),
                    beam.tgtOffset.getZ())
        
    
    def laserUpdateTask(self, task):
        frame = Vec4(0,0,1,1)
        
        t = time()
        self.generator.begin(base.cam,render)
        for beam in self.beams:
            progress = (t - beam.starttime) / beam.duration
            multiplier = 2*(0.5 - abs((0.5 - progress))) 
            width = multiplier * beam.maxwidth
            origin = Vec3(beam.turret.getPos(self.world))
            tgt = Vec3(beam.tgtNodePath.getPos(self.world))
            offset = self.getOffSet(beam)
            #print offset, tgt 
            tgt += offset
            self.generator.segment(origin, tgt, frame, width, beam.color)
            # update the light:
            lightColor = beam.color * multiplier
            beam.plight.setColor(lightColor)
        self.generator.end()
        
        # TODO: vaihda tietorakenteeseen josta voi poistaa vakioajassa
        n = len(self.beams)
        i = 0
        while i < n:
            beam = self.beams[i]
            if t - beam.starttime > beam.duration:
                beam.removeLight()
                self.beams.pop(i)
                n = n - 1
            i = i + 1
        
        return Task.cont